package org.kl.bpm.web.conf;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletRequest;

import org.activiti.engine.HistoryService;
import org.activiti.engine.ManagementService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricProcessInstanceQuery;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.history.HistoricTaskInstanceQuery;
import org.activiti.engine.impl.interceptor.Command;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.task.Task;
import org.activiti.engine.task.TaskQuery;
import org.apache.commons.lang3.StringUtils;
import org.kl.bf.entity.basic.User;
import org.kl.bf.entity.easyui.EasyuiGrid;
import org.kl.bf.entity.easyui.EasyuiUtils;
import org.kl.bf.entity.workflow.EProcessInstance;
import org.kl.bf.entity.workflow.ETask;
import org.kl.bf.service.basic.UserService;
import org.kl.bf.web.base.BasicController;
import org.kl.bpm.cmd.WithdrawTaskCmd;
import org.kl.bpm.entity.conf.BpmKvRecord;
import org.kl.bpm.service.conf.BpmKvRecordService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springside.modules.mapper.BeanMapper;
import org.springside.modules.utils.Collections3;
import org.springside.modules.web.MediaTypes;

/**
 * 工作流相关的个人事务
 * 
 * @Author hqm
 * @CreateTime 2014年6月10日 下午11:04:33
 */
@Controller
@RequestMapping(value = "/bpm/workspace")
public class BpmWorkspaceController extends BasicController {
	@Autowired
	private UserService userService;
	@Autowired
	private TaskService taskService;
	@Autowired
	private RuntimeService runtimeService;
	@Autowired
	private HistoryService historyService;
	@Autowired
	private ManagementService managementService;
	@Autowired
	private RepositoryService repositoryService;
	@Autowired
	private BpmKvRecordService bpmKvRecordService;

	protected static Map<String, ProcessDefinition> PROCESS_DEFINITION_CACHE = new HashMap<String, ProcessDefinition>();

	/**
	 * 打开页面-->>我发起的流程实例
	 * 
	 * @return
	 */
	@RequestMapping(value = "to-workspace-listRunningProcessInstances", produces = MediaTypes.JAVASCRIPT_UTF_8)
	public String to_listRunningProcessInstances() {
		return "bpm/workspace-listRunningProcessInstances";
	}

	/**
	 * 我发起的流程实例
	 * 
	 * @param pageNumber
	 * @param pageSize
	 * @param sortType
	 * @param orderType
	 * @param model
	 * @param request
	 * @return
	 */
	@RequestMapping(value = "workspace-listRunningProcessInstances", produces = MediaTypes.JAVASCRIPT_UTF_8)
	@ResponseBody
	public String listRunningProcessInstances(@RequestParam(value = "pageNumber", defaultValue = "1") int pageNumber,
			@RequestParam(value = "rows", defaultValue = PAGE_SIZE) int pageSize,
			@RequestParam(value = "sort", defaultValue = "id") String sortType,
			@RequestParam(value = "order", defaultValue = "desc") String orderType, Model model, ServletRequest request) {
		HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery()
				.startedBy(BasicController.getCurrentUserId()).unfinished();
		List<HistoricProcessInstance> historicProcessInstances = historicProcessInstanceQuery.orderByProcessInstanceStartTime().desc()
				.listPage(((pageNumber - 1) * pageSize), pageSize);
		List<EProcessInstance> epiList = new ArrayList<EProcessInstance>();
		for (HistoricProcessInstance hpi : historicProcessInstances) {
			EProcessInstance epi = BeanMapper.map(hpi, EProcessInstance.class);
			epiList.add(epi);
			if (StringUtils.isNotBlank(hpi.getStartUserId())) {
				User user = userService.getUser(hpi.getStartUserId());
				epi.setStarter(user == null ? "" : user.getTrueName());
			}
		}
		EasyuiGrid grid = new EasyuiGrid();
		grid.setRows(epiList);
		grid.setTotal((int) historicProcessInstanceQuery.count());
		String result = jsonMapper.toJson(grid);
		return result;
	}

	/**
	 * 打开页面-->>我发起的流程实例
	 * 
	 * @return
	 */
	@RequestMapping(value = "to-workspace-listInvolvedProcessInstances", produces = MediaTypes.JAVASCRIPT_UTF_8)
	public String to_listInvolvedProcessInstances() {
		return "bpm/workspace-listInvolvedProcessInstances";
	}

	/**
	 * 我参与的流程实例
	 * 
	 * @param pageNumber
	 * @param pageSize
	 * @param sortType
	 * @param orderType
	 * @param model
	 * @param request
	 * @return
	 */
	@RequestMapping(value = "workspace-listInvolvedProcessInstances", produces = MediaTypes.JAVASCRIPT_UTF_8)
	@ResponseBody
	public String listInvolvedProcessInstances(@RequestParam(value = "pageNumber", defaultValue = "1") int pageNumber,
			@RequestParam(value = "rows", defaultValue = PAGE_SIZE) int pageSize,
			@RequestParam(value = "sort", defaultValue = "id") String sortType,
			@RequestParam(value = "order", defaultValue = "desc") String orderType, Model model, ServletRequest request) {
		HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery().involvedUser(
				BasicController.getCurrentUserId());
		List<HistoricProcessInstance> historicProcessInstances = historicProcessInstanceQuery.orderByProcessInstanceStartTime().desc()
				.listPage(((pageNumber - 1) * pageSize), pageSize);
		List<EProcessInstance> epiList = new ArrayList<EProcessInstance>();
		for (HistoricProcessInstance hpi : historicProcessInstances) {
			EProcessInstance epi = BeanMapper.map(hpi, EProcessInstance.class);
			epiList.add(epi);
			if (StringUtils.isNotBlank(hpi.getStartUserId())) {
				User user = userService.getUser(hpi.getStartUserId());
				epi.setStarter(user == null ? "" : user.getTrueName());
			}
		}
		EasyuiGrid grid = new EasyuiGrid();
		grid.setRows(epiList);
		grid.setTotal((int) historicProcessInstanceQuery.count());
		String result = jsonMapper.toJson(grid);
		return result;
	}

	/**
	 * 打开页面-->>我的待办任务
	 * 
	 * @return
	 */
	@RequestMapping(value = "to-workspace-listPersonalTasks", produces = MediaTypes.JAVASCRIPT_UTF_8)
	public String to_listPersonalTasks() {
		return "bpm/workspace-listPersonalTasks";
	}

	/**
	 * 我的待办任务
	 * 
	 * @param pageNumber
	 * @param pageSize
	 * @param sortType
	 * @param orderType
	 * @param model
	 * @param request
	 * @return
	 */
	@RequestMapping(value = "workspace-listPersonalTasks", produces = MediaTypes.JAVASCRIPT_UTF_8)
	@ResponseBody
	public String listPersonalTasks(@RequestParam(value = "pageNumber", defaultValue = "1") int pageNumber,
			@RequestParam(value = "rows", defaultValue = PAGE_SIZE) int pageSize,
			@RequestParam(value = "sort", defaultValue = "id") String sortType,
			@RequestParam(value = "order", defaultValue = "desc") String orderType, Model model, ServletRequest request) {
		TaskQuery taskQuery = taskService.createTaskQuery().taskAssignee(BasicController.getCurrentUserId()).active();
		List<Task> taskList = taskQuery.orderByTaskCreateTime().desc().listPage(((pageNumber - 1) * pageSize), pageSize);
		List<ETask> epiList = new ArrayList<ETask>();
		for (Task t : taskList) {
			String processDefinitionId = t.getProcessDefinitionId();
			ProcessDefinition processDefinition = getProcessDefinition(processDefinitionId);
			BpmKvRecord kvRecord = bpmKvRecordService.findByRef(t.getProcessInstanceId());
			ETask eTask = packageTaskInfo(t, processDefinition);
			eTask.setStatus(ETask.TODO);
			epiList.add(eTask);
			if (StringUtils.isNotBlank(t.getAssignee())) {
				User user = userService.getUser(t.getAssignee());
				eTask.setAssigneeName(user == null ? "" : user.getTrueName());
				eTask.setPromoter(kvRecord.getCreateMan());
			}

			String lastTaskMan="";
			List<HistoricTaskInstance> historicTasks = historyService.createHistoricTaskInstanceQuery().processInstanceId(t.getProcessInstanceId()).orderByHistoricTaskInstanceStartTime().desc()
					.orderByHistoricTaskInstanceStartTime().desc().list();
			for(HistoricTaskInstance hiTask :historicTasks){
				if(hiTask.getEndTime()==null){					
					
				}else{
					User user = userService.getUser(hiTask.getAssignee());
					lastTaskMan=user!=null?user.getTrueName():"";
					break;
				}
			}
			eTask.setLastTaskMan(lastTaskMan);
		}
		return EasyuiUtils.buildEasyuiGridJsonString(epiList, (int) taskQuery.count());
	}

	/**
	 * 我的待办任务条数
	 * 
	 * @return
	 */
	@RequestMapping(value = "workspace-listPersonalTasks-count", produces = MediaTypes.JAVASCRIPT_UTF_8)
	@ResponseBody
	public String listPersonalTasksCount() {
		TaskQuery taskQuery = taskService.createTaskQuery().taskAssignee(BasicController.getCurrentUserId()).active();
		return ajaxMsg("我的待办任务条数获取成功", true, taskQuery.count());
	}

	/**
	 * 打开页面-->>我的待领任务
	 * 
	 * @return
	 */
	@RequestMapping(value = "to-workspace-listGroupTasks", produces = MediaTypes.JAVASCRIPT_UTF_8)
	public String to_listGroupTasks() {
		return "bpm/workspace-listGroupTasks";
	}

	/**
	 * 我的待领任务
	 * 
	 * @param pageNumber
	 * @param pageSize
	 * @param sortType
	 * @param orderType
	 * @param model
	 * @param request
	 * @return
	 */
	@RequestMapping(value = "workspace-listGroupTasks", produces = MediaTypes.JAVASCRIPT_UTF_8)
	@ResponseBody
	public String listGroupTasks(@RequestParam(value = "pageNumber", defaultValue = "1") int pageNumber,
			@RequestParam(value = "rows", defaultValue = PAGE_SIZE) int pageSize,
			@RequestParam(value = "sort", defaultValue = "id") String sortType,
			@RequestParam(value = "order", defaultValue = "desc") String orderType, Model model, ServletRequest request) {
		TaskQuery taskQuery = taskService.createTaskQuery().taskCandidateUser(BasicController.getCurrentUserId()).active();
		List<Task> taskList = taskQuery.orderByTaskCreateTime().desc().listPage(((pageNumber - 1) * pageSize), pageSize);
		int total = (int) taskQuery.count();
		List<String> roleNoList = BasicController.getCurrentUserRoleNoList();
		if (!Collections3.isEmpty(roleNoList)) {
			TaskQuery taskQuery2 = taskService.createTaskQuery().taskCandidateGroupIn(roleNoList).active();
			List<Task> toClaimList = taskQuery2.orderByTaskCreateTime().desc().listPage(((pageNumber - 1) * pageSize), pageSize);
			taskList.addAll(toClaimList);
			total += (int) taskQuery2.count();
		}
		List<ETask> epiList = new ArrayList<ETask>();
		for (Task t : taskList) {
			String processDefinitionId = t.getProcessDefinitionId();
			ProcessDefinition processDefinition = getProcessDefinition(processDefinitionId);

			ETask eTask = packageTaskInfo(t, processDefinition);
			eTask.setStatus(ETask.CLIAM);
			epiList.add(eTask);
			if (StringUtils.isNotBlank(t.getAssignee())) {
				User user = userService.getUser(t.getAssignee());
				eTask.setAssigneeName(user == null ? "" : user.getTrueName());
			}
		}
		return EasyuiUtils.buildEasyuiGridJsonString(epiList, total);
	}

	/**
	 * 打开页面-->>我的已办任务
	 * 
	 * @return
	 */
	@RequestMapping(value = "to-workspace-listHistoryTasks", produces = MediaTypes.JAVASCRIPT_UTF_8)
	public String to_listHistoryTasks() {
		return "bpm/workspace-listHistoryTasks";
	}

	/**
	 * 我的已办任务
	 * 
	 * @param pageNumber
	 * @param pageSize
	 * @param sortType
	 * @param orderType
	 * @param model
	 * @param request
	 * @return
	 */
	@RequestMapping(value = "workspace-listHistoryTasks", produces = MediaTypes.JAVASCRIPT_UTF_8)
	@ResponseBody
	public String listHistoryTasks(@RequestParam(value = "pageNumber", defaultValue = "1") int pageNumber,
			@RequestParam(value = "rows", defaultValue = PAGE_SIZE) int pageSize,
			@RequestParam(value = "sort", defaultValue = "id") String sortType,
			@RequestParam(value = "order", defaultValue = "desc") String orderType, Model model, ServletRequest request) {
		HistoricTaskInstanceQuery historicTaskInstanceQuery = historyService.createHistoricTaskInstanceQuery()
				.taskAssignee(BasicController.getCurrentUserId()).finished();
		List<HistoricTaskInstance> taskList = historicTaskInstanceQuery.orderByHistoricTaskInstanceEndTime().desc()
				.listPage(((pageNumber - 1) * pageSize), pageSize);
		List<ETask> epiList = new ArrayList<ETask>();
		for (HistoricTaskInstance t : taskList) {
			ETask et = BeanMapper.map(t, ETask.class);
			BpmKvRecord kvRecord = bpmKvRecordService.findByRef(t.getProcessInstanceId());
			String processDefinitionId=et.getProcessDefinitionId();
			//ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery().singleResult();
			ProcessDefinition processDefinition=repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
			
			//设置流程定义的名称
			et.setPdname((processDefinition.getName()==null)?"":processDefinition.getName());
			et.setCreateTime(t.getStartTime());
			et.setPromoter(kvRecord==null?"":kvRecord.getCreateMan());
			epiList.add(et);
			if (StringUtils.isNotBlank(t.getAssignee())) {
				User user = userService.getUser(t.getAssignee());
				et.setAssigneeName(user == null ? "" : user.getTrueName());
			}
		}
		EasyuiGrid grid = new EasyuiGrid();
		grid.setRows(epiList);
		grid.setTotal((int) historicTaskInstanceQuery.count());
		String result = jsonMapper.toJson(grid);
		return result;
	}

	/**
	 * 撤销任务
	 */
	@RequestMapping("workspace-witwithdrawhdraw")
	@ResponseBody
	public String withdraw(@RequestParam("taskId") String taskId) {
		Map<Integer, String> resultMap = new HashMap<Integer, String>();
		resultMap.put(0, "撤销成功");
		resultMap.put(1, "流程结束");
		resultMap.put(2, "下一结点已经通过,不能撤销");
		Command<Integer> cmd = new WithdrawTaskCmd(taskId);
		Integer result = 3;
		try {
			result = managementService.executeCommand(cmd);
		} catch (Exception e) {
			e.printStackTrace();
			return ajaxMsg("撤销任务失败[" + e.getMessage() + "]", true, null);
		}
		// 0-撤销成功 1-流程结束 2-下一结点已经通过,不能撤销
		return ajaxMsg(resultMap.get(result), true, null);
	}

	private ProcessDefinition getProcessDefinition(String processDefinitionId) {
		ProcessDefinition processDefinition = PROCESS_DEFINITION_CACHE.get(processDefinitionId);
		if (processDefinition == null) {
			processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
			PROCESS_DEFINITION_CACHE.put(processDefinitionId, processDefinition);
		}
		return processDefinition;
	}

	private ETask packageTaskInfo(Task task, ProcessDefinition processDefinition) {
		ETask eTask = new ETask();
		eTask.setId(task.getId());
		eTask.setName(task.getName());
		eTask.setCreateTime(task.getCreateTime());
		eTask.setPdname(processDefinition.getName());
		eTask.setPdversion(processDefinition.getVersion());
		eTask.setPid(task.getProcessInstanceId());
		return eTask;
	}
}
